// stores/useWs.js websocket全局管理
import { defineStore } from "pinia";
import { ref, watch } from "vue";
import { storeToRefs } from "pinia";
import Recorder from "@/pages/index/js/record";
import _audioCtx from "@/pages/index/js/play";
import SoketTask from "@/utils/ws.js";
import useChat from "@/store/useChat.js";
import useVoice from "@/store/useVoice.js";
import useAgent from "@/store/useAgent.js";
const useChatStore = useChat();
const useVoiceStore = useVoice();
const useAgentStore = useAgent();
import useLogin from "@/store/useLogin.js";
const useLoginStore = useLogin();
const useWs = defineStore("useWs", () => {
  const _ws = ref({});

  const { agentInfo } = storeToRefs(useAgentStore);
  const { recorderStatus, isCloseMic } = storeToRefs(useVoiceStore);

  //每一条回复的临时id记录 需要注意一下清空
  let tempId,
    flag = false;
  let _recorderManager = new Recorder(); //录音管理器
  // let _audioCtx = new AudioContext(); //语音播放器

  //关闭页面
  const onCloseVoiceChat = (t) => {
    _recorderManager?.stop(); //暂停录音
    useChatStore.userInputText = ""; //清空用户语音识别
    useChatStore.clientReplayText = ""; //清除智能体回复
    useChatStore.waitReplay = false; //重置等待状态
    useVoiceStore.resetVoiceStatus();
    _audioCtx.close();
    if (t) {
      nextTick(() => {
        uni.navigateBack();
      });
    }
  };
  watch(isCloseMic, (newVal) => {
    if (newVal) {
      stopRecorder();
    } else {
      startRecorder();
    }
  });

  //监听录音状态
  watch(recorderStatus, (newVal) => {
    if (
      useVoiceStore.chatType == 2 &&
      useLoginStore.userDeviceSystem != "android"
    ) {
      if (newVal == 2) {
        stopRecorder();
      } else if (newVal == 4) {
        if (isCloseMic.value) {
          return;
        }
        startRecorder();
      }
    }
  });

  //对讲模式 发送文字
  const sendTextToAgent = (content, cb) => {
    if (content.trim() == "") {
      return;
    }
    _ws.value
      .sendMessage({
        content: content,
        online: 1,
        recordStop: true,
      })
      .then((res) => {
        //发送消息成功
        if (cb) {
          cb(res);
        }
      });
  };

  //开始录音 切片回调
  const startRecorder = (data) => {
    _ws.value?.sendMessage({ ...{ recordStart: true }, ...data });
    recorderStatus.value = 1; //录音中
    _recorderManager?.start(onFrameRecorded);
  };

  // 监听录音帧变化 发送切片
  const onFrameRecorded = (res) => {
    //这里判断只有在录音状态下才发送切片，否则在结束录音的时候可能还会在期间生成的切片没发的继续发
    if (
      useLoginStore.userDeviceSystem != "android" &&
      recorderStatus.value == 1
    ) {
      _ws.value?.sendBufferMessage(res.frameBuffer);
    } else {
      _ws.value?.sendBufferMessage(res.frameBuffer);
    }
  };

  //存储本地缓存=>聊天记录
  const saveStorageMessage = (data) => {
    if (data.content.trim() == "") return;
    if (data.roleType == "HUMAN") {
      useChatStore.waitReplay = true;
    }
    useChatStore.sendMessage(data); //缓存本地
    useChatStore.clientReplayText = "";
    useChatStore.userInputText = "";
  };

  // 初始化ws
  const initWs = () => {
    _ws.value = new SoketTask({
      // url: "wss://aivoice-backend.idadt.com/test/gate_for_avatar",
      url: "wss://aivoice-backend.idadt.com/test/gate_for_avatar",
    });
    _ws.value.openCb = onWsOpen;
    _ws.value.connection();
    _ws.value.messageCb = onWsMessage;
    _ws.value.closeCb = onWsClose;
  };

  // ws打开 发送初始数据 打开录音
  const onWsOpen = () => {
    const request = {
      user_id: uni.getStorageSync("currentUserId"),
      agent_id: agentInfo.value.agentId,
      op_name: agentInfo.value.type,
      voice_id: agentInfo.value.voiceId == "null" ? 1 : agentInfo.value.voiceId,
      voice_name: agentInfo.value.voiceName || "海绵宝宝",
      online: useVoiceStore.chatType,
      conversation_group_id: useChatStore.currentSessionId,
    };
    _ws.value?.sendMessage(request);
    //实时语音才直接开启录音 对讲需要手动长按开启
    if (useVoiceStore.chatType == 2) {
      startRecorder();
    }
  };

  // ws收到信息
  const onWsMessage = (e) => {
    if (e.data instanceof ArrayBuffer) {
      // 收到二进制数据
      _audioCtx.addArrayBuffer(e.data);
    } else {
      //收到json数据

      try {
        let data = JSON.parse(e.data); //返回的json

        if (data.type == "asr" && data.msgTxt) {
          if (useVoiceStore.isPlaying) {
            _audioCtx.interruptVoice();
            _audioCtx.close();
          }
          console.log("********输入**********" + JSON.stringify(data));
          /**
           * 收到asr返回的数据
           *    stat:end ，代表此次输入已经识别到断点，可能会有多个断点，所以先暂存userInputText
           *    此时msgTxt包含此断点之前所有识别到的文字
           *    等本次输入开始输出tts数据时，才是真正的完全识别输入的语音，再把userInputText放到缓存
           */
          if (data.stat == "end") {
            useChatStore.userInputText = data.msgTxt;
          } else {
            /**
             * 流式返回的文字 每次用store里的userInputText叠加，然后再存store
             */
            let str = (useChatStore.userInputText += data.msgTxt);
            useChatStore.userInputText = str;
          }
        }
        if (data.type == "tts") {
          flag = data.is_break;
          /**
           * 收到tts返回的数据
           * {
           *  type:tts, //类型
           *  is_end(本次tts返回的文字是否已结束):true,
           *  is_break:true, //有此标识代表本次在tts回复时，用户新输入了，本次被打断
           *  msgTxt:xxxxxx //tts生成的回复，每一句话
           * }
           */
          console.log("********输出**********" + JSON.stringify(data));
          if (data.msgTxt && !data.is_break) {
            /**
             * 收到tts回复第一件事先把之前识别到的输入的文字存缓存
             * 实时语音需要修改交互状态 对讲直接保存就行了
             * 然后更新录音状态 (判断1是因为只存一次,0是对讲模式的状态)
             */
            if (useVoiceStore.chatType == 2) {
              //实时语音模式 打断情况先不存入缓存 等下一条tts回复进来再存
              if (!flag) {
                saveStorageMessage({
                  content: useChatStore.userInputText,
                  roleType: "HUMAN",
                });
              }
              if (recorderStatus.value == 1) {
                recorderStatus.value = 2; //等待播放
              }
            } else {
              saveStorageMessage({
                content: useChatStore.userInputText,
                roleType: "HUMAN",
              });
            }

            //延时展示
            // setTimeout(() => {
            //流式返回 *输出* 的tts文字，根据tempId作为唯一值做查找，push到messages列表里，添加完了清空，
            //这里放延时是 先播放音频，再出现文字 ，暂定1秒
            let str = useChatStore.clientReplayText + data.msgTxt;
            if (tempId) {
              useChatStore.setStreamMessageByTempId(tempId, str);
            } else {
              tempId = new Date().getTime();
              saveStorageMessage({
                content: str,
                roleType: "ASSISTANT",
                tempId: tempId,
              });
            }

            useChatStore.clientReplayText = str;
            useChatStore.waitReplay = false;
            // }, 1000);
          } else if (data.is_end && !data.is_break) {
            //流式返回 *输出* 接收文字完毕 放缓存
            //由于上边延时展示文字，所以这里也需要延时去取，否则会不完整
            console.log("结束接收tts,没有被打断");
            // setTimeout(() => {
            tempId = null;
            useChatStore.clientReplayText = "";
            // }, 1000);
          } else if (data.is_break) {
            // setTimeout(() => {
            console.log("收到打断信号了");

            tempId = null;
            useChatStore.clientReplayText = "";
            useChatStore.waitReplay = true;
            //请缓冲区和预加载区
            _audioCtx.interruptVoice();
            _audioCtx.close();
            // }, 1000);
          }
        }
      } catch (e) {
        if (e.data == "音频播放结束") {
          //这里只是代表一句回复的二进制文件接收结束了，并不是前端播放音频结束和此次完整的回复二进制接收完毕
          return;
        }
      }
    }
  };
  //ws断开 t：true代表主动关闭 关闭当前页操作
  const onWsClose = (t) => {
    _recorderManager?.stop();
    recorderStatus.value = null;
    if (t) return;
    uni.showToast({
      icon: "none",
      title: "连接已断开，请稍后重试",
    });
  };

  //中断播放，后续还得继续接收文字聊天记录存缓存，
  const interruptVoice = () => {
    _audioCtx.interruptVoice();
  };

  //暂停录音
  const stopRecorder = (t) => {
    _recorderManager?.stop();
    //对讲模式 调用本方法recorderStatus未置为2，所以在此处更新状态
    //否则在onFrameRecorded无法立即停止发送切片
    if (useVoiceStore.chatType == 1) {
      recorderStatus.value = 0;
    }
    _ws.value?.sendMessage({ recordStop: true });
  };

  //对讲模式 取消发送语音
  const cancleSendVoice = () => {
    console.log("用户取消发送语音");
    tempId = null; //本次tempId重置
    //取消发送userInputText还没存到缓存，页面上显示的是userInputText，所以置为空即可
    useChatStore.userInputText = "";
    _ws.value.sendMessage({ cancel: true });
  };

  return {
    _ws,
    _audioCtx,
    _recorderManager,
    isCloseMic,
    initWs,
    onWsOpen,
    startRecorder,
    cancleSendVoice,
    stopRecorder,
    sendTextToAgent,
    onCloseVoiceChat,
    interruptVoice,
  };
});

export default useWs;
